//---------------------------------------------------------------------
// File: DBExecuteNonQueryStep.cs
// 
// Summary: 
//---------------------------------------------------------------------

using System;
using System.Threading;
using System.Xml;


namespace BizUnit.Extensions.EntLib
{

    using Utilities;

    /// <summary>
    /// The EntLibDBExecuteNonQueryStep executes a non-query SQL statement. The number of rows affected is asserted if the 
    /// NumberOfRowsAffected element is specified
    /// </summary>
    /// 
    /// <remarks>
    /// The following shows an example of the Xml representation of this test step.
    /// 
    /// <code escaped="true">
    ///	<TestStep assemblyPath="" typeName="BizUnit.DBExecuteNonQueryStep">
    ///		<DelayBeforeExecution>1</DelayBeforeExecution>
    ///		<ConfigFileLocation>..\\..\\db.config</ConnectionString>
    ///		<DatabaseConfigName>Northwind</DatabaseConfigName>
    ///		<NumberOfRowsAffected></NumberOfRowsAffected>
    ///
    ///		<!-- 
    ///		The SQL Query to execute is built by formatting the RawSQLQuery substituting in the 
    ///		SQLQueryParam's
    ///		-->
    ///		<SQLQuery>
    ///			<RawSQLQuery>INSERT INTO TABLE (COLUMN1, COLUMN2) VALUES (VALUE1, {0},{1} )</RawSQLQuery>
    ///			<SQLQueryParams>
    ///				<SQLQueryParam takeFromCtx="Key1"></SQLQueryParam>
    ///				<SQLQueryParam takeFromCtx="Key2"></SQLQueryParam>
    ///			</SQLQueryParams>
    ///		</SQLQuery>
    ///	</TestStep>
    ///	</code>
    ///	
    ///	<list type="table">
    ///		<listheader>
    ///			<term>Tag</term>
    ///			<description>Description</description>
    ///		</listheader>
    ///		<item>
    ///			<term>DelayBeforeExecution</term>
    ///			<description>The number of seconds to wait before executing the step</description>
    ///		</item>
    ///		<item>
    ///			<term>ConfigFileLocation</term>
    ///			<description>The config file containing the Enterprise Library configuration for db access</description>
    ///		</item>
    ///     <item>
    ///			<term>DatabaseConfigName</term>
    ///			<description>The config section name of the databased used in the test</description>
    ///		</item>
    /// 
    ///		<item>
    ///			<term>NumberOfRowsAffected</term>
    ///			<description>The number of rows affected. This is an optional element. If specified, it causes the test step to raise an exception when the number of rows affected
    ///						by executing the non-query does not match the specified value</description>
    ///		</item>
    ///		<item>
    ///			<term>SQLQuery/RawSQLQuery</term>
    ///			<description>The raw SQL string that will be formatted by substituting in the SQLQueryParam</description>
    ///		</item>
    ///		<item>
    ///			<term>SQLQuery/SQLQueryParams/SQLQueryParam</term>
    ///			<description>The parameters to substitute into RawSQLQuery <para>(repeating)</para></description>
    ///		</item>
    ///	</list>
    ///	</remarks>	
    public class EntLibDBExecuteNonQueryStep : ITestStep
    {
        private string configFileLocation;
        private string databaseConfigName;
        private int delayBeforeCheck;

        public string ConfigFileLocation
        {
            get
            {
                return configFileLocation;
            }
            set
            {
                configFileLocation = value;
            }
        }
        public string DatabaseConfigName
        {
            get
            {
                return databaseConfigName;
            }
            set
            {
                databaseConfigName = value;
            }
        }

        public int DelayBeforeCheck
        {
            get
            {
                return delayBeforeCheck;
            }
            set
            {
                delayBeforeCheck = value;
            }
        }
        /// <summary>
        /// ITestStep.Execute() implementation
        /// </summary>
        /// <param name='testConfig'>The Xml fragment containing the configuration for this test step</param>
        /// <param name='context'>The context for the test, this holds state that is passed beteen tests</param>
        public void Execute(XmlNode testConfig, Context context)
        {
            ConfigFileLocation = context.ReadConfigAsString(testConfig, "ConfigFileLocation");
            DatabaseConfigName = context.ReadConfigAsString(testConfig, "DatabaseConfigName");

            DelayBeforeCheck = context.ReadConfigAsInt32(testConfig, "DelayBeforeExecution");
            XmlNode queryConfig = testConfig.SelectSingleNode("SQLQuery");
            int numberOfRowsAffected = testConfig.InnerXml.IndexOf("NumberOfRowsAffected", 0, testConfig.InnerXml.Length) != -1 ? context.ReadConfigAsInt32(testConfig, "NumberOfRowsAffected") : -1;

            string sqlQuery = EntLibDatabaseHelper.BuildSQLQuery(queryConfig, context);

            context.LogInfo("Using database connection string from config file: {0}", configFileLocation);
            context.LogInfo("Executing query: {0}", sqlQuery);

            // Sleep for delay seconds...
            Thread.Sleep(DelayBeforeCheck * 1000);

            int rowCount = EntLibDatabaseHelper.ExecuteNonQuery(configFileLocation, databaseConfigName, sqlQuery);

            if (numberOfRowsAffected != -1)
            {
                if (rowCount != numberOfRowsAffected)
                    throw new Exception("Number of rows affected by the query does not match the value specified in the teststep. Number of rows affected was " + rowCount.ToString() + " and value specified was " + numberOfRowsAffected.ToString());
            }
            else
            {
                context.LogInfo("The number of rows affected by the query matched the value specified in the test step. " + rowCount.ToString() + "  rows were affected");
            }
        }
    }
}
